/*
|-----------------------------------------------------------------------------|
| Overall ANTLR Grammar File Structure                                        |
|-----------------------------------------------------------------------------|
| «grammarType» grammar name;
|   «optionsSpec»     = options { ... }
|   «tokensSpec»      = tokens { ... }
|   «attributeScopes» = «@action-scope-name::action-name» { ... }
|   «actions»
|   // rules
|   rule1 : ... ;
|   rule2 : ... ;
|   ...
|_____________________________________________________________________________|
|   «grammarType»         = ( lexer | parser | tree | <empty> )
|   «optionsSpec»         = options { ... }
|   «tokensSpec»          = tokens { ... }
|   «attributeScopes»     = 
|   «actions»             = @«action-scope-name»::«action-name» { ... }
|    «action-scope-name» = ( lexer | parser | tree | <empty> = parser )
|    «action-name»       = ( header | members | rulecatch | synpredgate )
|-----------------------------------------------------------------------------|
*/
/**
* @asignatura: Procesadores de Lenguajes.
* @autor: Anthony Vittorio Russo Cabrera
* @curso: 2012/2013
* @práctica: 07 - YACC
*
*/
lexer grammar YACCLexer;

  options {
    language = Java;
  }// options
  
  @lexer::header {
    package pl.p07.antlr3;
  }//header
  @lexer::members {
  }// members

//= Lexer Rules YACC =========================================================|
  /* Palabras reservadas */
  DefStart    : '%start';
  DefToken    : '%token';
  DefType     : '%type';
  DefLeft     : '%left';
  DefRight    : '%rigth';
  DefUnion    : '%union';
  DefNonAssoc : '%nonassoc';
  DefPrec     : '%prec';
  
  /* Símbolos especiales */  
  DefReturns  : '$' ((Digit)+ | '$');
  BlockDivider  : '%%';
  BeginCopyBlock: '%{';
  EndCopyBlock  : '%}';

//= Lexer Rules C ============================================================|
  /* Tipos de datos */
  Void     : 'void';
  Int      : 'int';
  Char     : 'char';
  Float    : 'float';
  Short    : 'short';
  Signed   : 'signed';
  Long     : 'long';
  Double   : 'double';
  Unsigned : 'unsigned';

  /* Palabras reservadas */
  Include  : 'include';
  Define   : 'define';
  Typedef  : 'typedef';
  If       : 'if';
  Else     : 'else';
  While    : 'while';
  For      : 'for';
  Do       : 'do';
  Switch   : 'switch';
  Case     : 'case';
  Default  : 'default';
  Break    : 'break';
  Continue : 'continue';
  Goto     : 'goto';
  True     : 'true';
  False    : 'false';
  Return   : 'return';
  Const    : 'const';
  Enum     : 'enum';
  Union    : 'union';
  Struct   : 'struct';
	//Sizeof   : 'sizeof';
	//Volatile : 'volatile';
	//Extern   : 'extern';
	//Static   : 'static';
	//Auto     : 'auto';
	//Register : 'register';

  /* Nueva línea */
  fragment NewLine: '\r'? '\n';

  /* Espacios */
  WhiteSpace : (' '|'\r'|'\t'|'\u000C'|'\n') { $channel=HIDDEN; skip(); };

  /* Dígitos */
  fragment Digit: ('0'..'9') ;
  fragment HexDigit : (Digit|'a'..'f'|'A'..'F') ;
  fragment OctalDigit : ('0'..'7') ;

  /* Números */
  HexLiteral : '0' ('x'|'X') HexDigit+ ;
  DecimalLiteral : ('0' | '1'..'9' Digit*) ;
  OctalLiteral : '0' (OctalDigit)+ ;
  fragment Exponent : ('e'|'E') ('+'|'-')? ('0'..'9')+ ;
  FloatingPointLiteral :   (Digit)+ '.' (Digit)* Exponent? ;

  /* Letras */
  fragment LetterLower: ('a'..'z');
  fragment LetterUpper: ('A'..'Z');
  fragment Letter: (LetterLower|LetterUpper|'_');

  /* Identificadores */
  Identifier: Letter (Letter | Digit)*;

  /* Cadenas */
  fragment EscapeSequence
    :   '\\' ('b'|'t'|'n'|'f'|'r'|'\"'|'\''|'\\')
    |   OctalEscape
    ;
  fragment OctalEscape
    :   '\\' ('0'..'3') OctalDigit OctalDigit
    |   '\\' OctalDigit OctalDigit
    |   '\\' OctalDigit
    ;
  CharacterLiteral: '\'' ( EscapeSequence | ~('\''|'\\') ) '\'' ;
  StringLiteral: '"' (options {greedy=false;}: (EscapeSequence|~('\\'|'"')) )* '"';

  /* Separadores */
  LeftParenthesis     : '(';
  RightParenthesis    : ')';
  LeftBracket         : '{';
  RightBracket        : '}';
  LeftSquareBracket   : '[';
  RightSquareBracket  : ']';
  Colon               : ':';
  SemiColon           : ';';
  Comma               : ',';
  Dot                 : '.';

  /* Operadores */
  Equal           : '==';
  NotEqual        : '!=';
  LessEqual       : '<=';
  GreaterEqual    : '>=';
  LeftShift       : '<<';
  RightShift      : '>>';
  And             : '&&';
  Or              : '||';
  MultiplyEqual   : '*=';
  DivideEqual     : '/=';
  ModEqual        : '%=';
  AddEqual        : '+=';
  SubEqual        : '-=';
  LeftShiftEqual  : '<<=';
  RightShiftEqual : '>>=';
  AndEqual        : '&=';
  ExpEqual        : '^=';
  OrEqual         : '|=';
  Increase        : '++';
  Decrease        : '--';
  Aim             : '->';
  Ellipsis        : '...';

  Assing        : '=';
  Not           : '!';
  Less          : '<';
  Greater       : '>';
  Plus          : '+';
  Minus         : '-';
  Asterisk      : '*';
  Ampersand     : '&';
  Stick         : '|';
  Slash         : '/';
  Question      : '?';
  NumberSign    : '#';
  Caret         : '^';
  Percent       : '%';
  Tilde         : '~';

  /* Comentarios */
  CommentLine
    : '//' ~('\n'|'\r')* NewLine  { $channel=HIDDEN; skip(); } 
    ;
  NestedCommentBlock
    : '/*' (options {greedy=false;} : (NestedCommentBlock | .))* '*/'
      { $channel=HIDDEN; skip(); }
    ;